home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
425_01
/
tar
/
restore.c
< prev
next >
Wrap
Text File
|
1994-04-02
|
16KB
|
571 lines
/* restore.c - extract regular files from (tape) archive.
* This is a part of the Tar program (see file tar.c)
* Author: T.V.Shaporev
* Creation date: 11 Mar 1993
*/
#include <stdio.h>
#include <errno.h>
#include "sysup.h"
#include "modern.h"
#ifdef MODERN
# include <string.h>
#else
char *strncpy();
int strlen();
#endif
#ifdef MSDOS
# include <io.h>
# include <dos.h>
# include <stdlib.h>
# ifdef __TURBOC__
# include <dir.h>
# else
# include <direct.h>
# endif
#else
int access(), creat(), open(), close(), link(), unlink();
int write(), chown(), utime();
char *malloc();
long lseek();
void free();
#endif
#include "lzwbits.h"
#include "lzwhead.h"
#include "compress.h"
#include "define.h"
#include "lzpack.h"
char ofname[MAXTNAME
#ifdef MSDOS
+MAXFILE
#endif
+1];
void extwrerr()
{
(void)fprintf(myout, "Tar: error extracting \'%s\'\n", ofname);
done(EWRITE);
}
#ifdef MSDOS
static void setime __ARGS__(( int, long ));
static void setime(h, mt)
int h; long mt;
{
struct date d;
struct time t;
struct ftime f;
if (m_flag) return;
unixtodos(mt, &d, &t);
f.ft_tsec = t.ti_sec;
f.ft_min = t.ti_min;
f.ft_hour = t.ti_hour;
f.ft_day = d.da_day;
f.ft_month = d.da_mon;
f.ft_year = d.da_year - 1980;
(void)setftime(h, &f);
}
#define wcnt_type unsigned short
#define MAXWARN 8
static renamed = FALSE;
static wcnt_type wcount = 0;
static nwarn = 0;
static struct { wcnt_type lru; char wnm[MAXTNAME]; } wlist[MAXWARN];
static void wrename __ARGS__(( char * ));
static void wrename(n)
char *n;
{
register i;
renamed = FALSE;
for (i=0; i<nwarn; i++) {
if (strncmp(wlist[i].wnm, n, MAXTNAME) == 0) {
wlist[i].lru = wcount++; return;
}
}
(void)printf("Tar: warning: renamed to \'%s\'\n", n);
if (nwarn < MAXWARN) {
i = nwarn++;
} else {
register j;
/* Find the least recently used entry */
for (i=0, j=1; j<MAXWARN; j++) {
if (wlist[j].lru < wlist[i].lru) i = j;
}
}
(void)strncpy(wlist[i].wnm, n, MAXTNAME);
wlist[i].lru = wcount++;
}
#define CH_DOT '-'
#define CH_BAD '$'
static void uname __ARGS__(( char * ));
static void uname(fname) /* convert UNIX file name to DOS */
char fname[];
{
static char invalid[] = "^+=/[]:;\',?*\\<>|\".";
register char *p = fname;
register i, offext/* offset to file name extension */;
register j, limcpy, tmpren;
if (p[1] == ':' && (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
p += 2;
tmpren = FALSE;
while (*p) {
if (*p == '/') {
++p; /* Forget dir name changes */ tmpren = FALSE;
}
for (offext=i=0; p[i] && p[i]!='/'; i++) {
if (p[i] == '.') {
if (i == 0) {
if (p[1]=='.' && p[2]=='/') {
/* This is '..' directory, skip */ ++i;
} else if (p[1]!='/') {
/* This is not current directory */
p[0] = CH_DOT; tmpren = TRUE;
}
} else {
if (offext) {
p[offext] = CH_DOT; tmpren = TRUE;
}
offext = i;
}
} else if (p[i]<=' ' || p[i]>'~' || strchr(invalid, p[i])) {
p[i] = CH_BAD; tmpren = TRUE;
}
}
if (!offext) offext = i;
limcpy = MAXTNAME - (int)(p-fname) - offext;
i -= offext;
if (offext <= 8) {
j = offext;
} else {
(void)strncpy(p+8, p+offext, i>4 ? 4 : limcpy);
tmpren = TRUE;
j = 8;
}
if (i <= 4) {
j += i;
} else {
(void)strncpy(p+(offext>8 ? 12 : offext+4), p+i+offext, limcpy-i);
tmpren = TRUE;
j += 4;
}
p += j;
}
if (tmpren) renamed = TRUE;
}
#else
# define setime(h,t)
# define uname(s)
#endif
int makedir __ARGS__((char *, int));
int testdir __ARGS__((char *));
/*ARGSUSED*/ int makedir(p, to_print)
char *p; int to_print;
{
#ifdef UNIX
# ifdef RMKDIR
if (mkdir(p, 0777) != 0 && to_print) {
(void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
return ERROR;
}
# else
switch (bincall("mkdir", p)) {
case 0: break;
case -1: (void)fprintf(myout, "Tar: fault run mkdir!\n");
default: done(0);
}
# endif
if (!o_flag) (void)chown(p,(int)st.st_uid,(int)st.st_gid);
#endif
#ifdef MSDOS
if (mkdir(p) != 0 && to_print) {
(void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
return ERROR;
}
#endif
return 0;
}
int testdir(p)
char *p;
{
register j;
register k = FALSE;
#ifndef UNIX
register char *q = p;
#endif
#ifdef MSDOS
renamed = FALSE;
#endif
for (j=1; j<MAXTNAME && p[j]; j++) {/* check directories */
if (p[j] == '/') {
p[j] = 0;
#ifndef UNIX
uname(q); q = p + j + 1;
#endif
if (access(p, 1) < 0) {
if (makedir(p, TRUE) != 0) return ERROR;
k = TRUE;
}
p[j] = '/';
}
}
#ifdef MSDOS
if (renamed && v_flag) wrename(p);
#endif
return k;
}
long thisread;
int arcget __ARGS__((void))
{
if (v_flag && !(thisread & 07777)) percent(thisread, st.st_size);
return thisread<st.st_size ? (++thisread, readbyte()) : EOF;
}
static int o_file, indput;
static long thiscsum;
static void dstput(c)
int c;
{
thiscsum += c; ((unsigned char *)pk_out)[indput++] = c;
if (indput >= pksize) {
if (write(o_file, pk_out, pksize) != pksize) {
if (v_flag) (void)fprintf(myout, "\n");
extwrerr();
}
indput = 0;
}
}
#define savename(s) ((void)strncpy(ofname,(s),MAXTNAME),ofname[MAXTNAME]='\0')
static int newfile __ARGS__(( char *, int ));
static int newfile(name, mode)
char *name; int mode;
{
#ifdef MSDOS
int h, caccess;
unsigned cmode;
register k = 0;
savename(name);
caccess = o_flag ? O_CREAT+O_EXCL+O_WRONLY+O_BINARY :
O_CREAT+O_TRUNC+O_WRONLY+O_BINARY;
cmode = (mode & 0444 ? S_IREAD : 0) |
(mode & 0222 ? S_IWRITE : 0) |
(mode & 0111 ? S_IEXEC : 0);
if ((h = open(name, caccess, cmode)) < 0) {
if (errno == ENOENT || errno == ENOPATH) {
if ((k=testdir(name)) == TRUE) h = open(name, caccess, cmode);
} else if (errno == EEXIST && o_flag) {
static char del[4] = "^~\'`";
register unsigned ntry = 0;
register nb, len, i, j;
char suffix[5];
if ((len = strlen(name)) > MAXTNAME) goto end;
for (nb=len; nb>0 && name[nb-1]!='/' && name[nb-1]!=':'; nb--) {
if (name[nb] == '.') len = nb;
}
len -= nb;
do {
++ntry;
/* Convert number of try into suffix */
suffix[0] = del[ntry & 3];
for (i=1, j=ntry>>2; j; j>>=5) {
suffix[i++] = ((j & 037) < 10 ? '0': 'A'-10) + (j & 037);
}
suffix[i] = '\0';
/* Replace end of the name by suffix */
if (len < 8) {
(void)strcat(
strcpy(ofname+nb+(len+i<8 ? len : 8-i), suffix),
name+nb+len);
} else {
(void)strncpy(ofname+nb+len-i, suffix, i);
}
renamed = TRUE;
h = open(ofname, caccess, cmode);
} while (h<0 && errno == EEXIST && ntry);
}
}
end:
if (h < 0) {
if (k!=ERROR) (void)fprintf(myout,"Tar: can\'t create \'%s\'\n",name);
} else {
if (renamed && v_flag) wrename(ofname);
if ((mode & 0777) == 0) (void)_chmod(name, 1, FA_HIDDEN);
}
return h;
#else
register j = 0;
register h;
savename(name);
do {
if ((h = creat(name, (int)(mode & 07777))) >